#include "preHeader.h"
#include "Session/GameSession.h"
#include "Session/GameSessionHandler.h"
#include "SQLHelper.h"

int GameSessionHandler::HandleLoadAllPlayerCharacterInfo(GameSession *pSession, INetPacket &pck, const RPCSession::RequestMetaInfo &info)
{
	auto LoadAllPlayerCharacterInfo = [GSRPCAsyncTaskArgs]() {
		AutoFeedbackLarge(buffer, error)
		auto connPtr = sMysqlDatabasePool.GetCharDB()->GetConnAutoPtr();
		if (!connPtr) {
			error = DBPErrorConnectMysqlFailed;
			return;
		}
		size_t n = 0;
		uint32 lastInstID = 0;
		auto sqlFormat = CreateSQL4SelectEntity<InstPlayerOutlineInfo>(
			"ipcInstID>%u AND ipcDeleteTime=0 ORDER BY ipcInstID");
mark:	auto rst = connPtr->FastQueryFormat(sqlFormat.c_str(), lastInstID);
		if (!rst) {
			error = DBPErrorQueryMysqlFailed;
			return;
		}
		while (rst.NextRow()) {
			auto row = rst.Fetch();
			auto instInfo = LoadEntityFromMysqlRow<InstPlayerOutlineInfo>(row);
			SaveToINetStream(instInfo, buffer);
			lastInstID = instInfo.ipcInstID;
			if (++n % 250 == 0) {
				GameSession::Feedback(gsPtr, buffer, info.sn, RPCErrorNone, false);
				buffer.Clear();
			}
		}
		if (connPtr->GetLastErrno() != 0) {
			goto mark;
		}
	};
	sDeferAsyncTaskMgr.AddTask(CreateAsyncTask(LoadAllPlayerCharacterInfo));
	return SessionHandleCapture;
}

int GameSessionHandler::HandleLoadAccountPlayerPreviewInfo(GameSession *pSession, INetPacket &pck, const RPCSession::RequestMetaInfo &info)
{
	auto LoadAccountPlayerPreviewInfo = [GSRPCAsyncTaskArgs]() {
		uint32 ipcAcctID, ipcServerID;
		(*pckPtr) >> ipcAcctID >> ipcServerID;
		AutoFeedbackLarge(buffer, error)
		auto connPtr = sMysqlDatabasePool.GetCharDB()->GetConnAutoPtr();
		if (!connPtr) {
			error = DBPErrorConnectMysqlFailed;
			return;
		}
		auto sqlFormat = CreateSQL4SelectEntity<InstPlayerPreviewInfo>(
			"ipcAcctID=%u AND ipcServerID=%u AND ipcDeleteTime=0");
		auto rst = connPtr->QueryFormat(sqlFormat.c_str(), ipcAcctID, ipcServerID);
		if (!rst) {
			error = DBPErrorQueryMysqlFailed;
			return;
		}
		while (rst.NextRow()) {
			auto row = rst.Fetch();
			auto instInfo = LoadEntityFromMysqlRow<InstPlayerPreviewInfo>(row);
			SaveToINetStream(instInfo, buffer);
		}
	};
	sAsyncTaskMgr.AddTask(CreateAsyncTask(LoadAccountPlayerPreviewInfo));
	return SessionHandleCapture;
}

int GameSessionHandler::HandleLoadOnePlayerCharacterInfo(GameSession *pSession, INetPacket &pck, const RPCSession::RequestMetaInfo &info)
{
	auto LoadOnePlayerCharacterInfo = [GSRPCAsyncTaskArgs]() {
		auto ipcInstID = pckPtr->Read<uint32>();
		AutoFeedbackLarge(buffer, error)
		auto connPtr = sMysqlDatabasePool.GetCharDB()->GetConnAutoPtr();
		if (!connPtr) {
			error = DBPErrorConnectMysqlFailed;
			return;
		}
		auto sqlFormat = CreateSQL4SelectEntity<InstPlayerOutlineInfo>(
			"ipcInstID=%u AND ipcDeleteTime=0");
		auto rst = connPtr->QueryFormat(sqlFormat.c_str(), ipcInstID);
		if (!rst) {
			error = DBPErrorQueryMysqlFailed;
			return;
		}
		if (rst.NextRow()) {
			auto row = rst.Fetch();
			auto instInfo = LoadEntityFromMysqlRow<InstPlayerOutlineInfo>(row);
			SaveToINetStream(instInfo, buffer);
		}
	};
	sAsyncTaskMgr.AddTask(CreateAsyncTask(LoadOnePlayerCharacterInfo));
	return SessionHandleCapture;
}

int GameSessionHandler::HandleNewOnePlayerInstance(GameSession *pSession, INetPacket &pck, const RPCSession::RequestMetaInfo &info)
{
	auto NewOnePlayerInstance = [GSRPCAsyncTaskArgs]() {
		inst_player_char instInfo;
		LoadFromINetStream(instInfo, *pckPtr);
		AutoFeedback(buffer, error)
		auto connPtr = sMysqlDatabasePool.GetCharDB()->GetConnAutoPtr();
		if (!connPtr) {
			error = DBPErrorConnectMysqlFailed;
			return;
		}
		auto sqlStr = CreateSQL4InsertEntity(instInfo);
		auto rst = connPtr->Execute(sqlStr.c_str());
		if (!rst.second) {
			error = DBPErrorInsertMysqlFailed;
			return;
		}
	};
	sAsyncTaskMgr.AddTask(CreateAsyncTask(NewOnePlayerInstance));
	return SessionHandleCapture;
}

int GameSessionHandler::HandleSaveOnePlayerInstance(GameSession *pSession, INetPacket &pck, const RPCSession::RequestMetaInfo &info)
{
	auto SaveOnePlayerInstance = [GSRPCAsyncTaskArgs]() {
		static const std::vector<ssize_t> ingores =
			ConvertEntityFieldIndexs<inst_player_char>({
			"ipcInstID","ipcAcctID","ipcNickName","ipcDeleteTime","ipcGsWriteValue"});
		inst_player_char instInfo;
		LoadFromINetStream(instInfo, *pckPtr);
		AutoFeedback(buffer, error)
		auto connPtr = sMysqlDatabasePool.GetCharDB()->GetConnAutoPtr();
		if (!connPtr) {
			error = DBPErrorConnectMysqlFailed;
			return;
		}
		auto sqlStr = CreateSQL4UpdateEntity(instInfo, "ipcInstID=%u", ingores);
		auto rst = connPtr->ExecuteFormat(sqlStr.c_str(), instInfo.ipcInstID);
		if (!rst.second) {
			error = DBPErrorUpdateMysqlFailed;
			return;
		}
	};
	sAsyncTaskMgr.AddTask(CreateAsyncTask(SaveOnePlayerInstance));
	return SessionHandleCapture;
}

int GameSessionHandler::HandleLoadOnePlayerInstance(GameSession *pSession, INetPacket &pck, const RPCSession::RequestMetaInfo &info)
{
	auto LoadOnePlayerInstance = [GSRPCAsyncTaskArgs]() {
		auto ipcInstID = pckPtr->Read<uint32>();
		AutoFeedbackLarge(buffer, error)
		auto connPtr = sMysqlDatabasePool.GetCharDB()->GetConnAutoPtr();
		if (!connPtr) {
			error = DBPErrorConnectMysqlFailed;
			return;
		}
		auto sqlFormat = CreateSQL4SelectEntity<inst_player_char>(
			"ipcInstID=%u AND ipcDeleteTime=0");
		auto rst = connPtr->QueryFormat(sqlFormat.c_str(), ipcInstID);
		if (!rst) {
			error = DBPErrorQueryMysqlFailed;
			return;
		}
		if (rst.NextRow()) {
			auto row = rst.Fetch();
			auto instInfo = LoadEntityFromMysqlRow<inst_player_char>(row);
			SaveToINetStream(instInfo, buffer);
		}
	};
	sAsyncTaskMgr.AddTask(CreateAsyncTask(LoadOnePlayerInstance));
	return SessionHandleCapture;
}

int GameSessionHandler::HandleDeleteOnePlayerInstance(GameSession *pSession, INetPacket &pck, const RPCSession::RequestMetaInfo &info)
{
	auto DeleteOnePlayerInstance = [GSRPCAsyncTaskArgs]() {
		auto playerId = pckPtr->Read<uint32>();
		AutoFeedback(buffer, error)
		auto connPtr = sMysqlDatabasePool.GetCharDB()->GetConnAutoPtr();
		if (!connPtr) {
			error = DBPErrorConnectMysqlFailed;
			return;
		}
		auto sqlFormat = "UPDATE `%s` SET ipcNickName=CONCAT_WS(',',"
			"ipcNickName,ipcInstID),ipcDeleteTime=%lld WHERE ipcInstID=%u";
		auto rst = connPtr->ExecuteFormat(sqlFormat,
			GetTableName<inst_player_char>(), (s64)GET_UNIX_TIME, playerId);
		if (!rst.second) {
			error = DBPErrorUpdateMysqlFailed;
			return;
		}
	};
	sAsyncTaskMgr.AddTask(CreateAsyncTask(DeleteOnePlayerInstance));
	return SessionHandleCapture;
}

int GameSessionHandler::HandleSaveMultiPlayerGsInfo(GameSession *pSession, INetPacket &pck, const RPCSession::RequestMetaInfo &info)
{
	return SessionHandleSuccess;
}
